home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib43 / mntlib / malloc.c < prev    next >
C/C++ Source or Header  |  1993-09-15  |  5KB  |  218 lines

  1. /* from the TOS GCC library */
  2. /* malloc, free, realloc: dynamic memory allocation */
  3. /* ERS: added mlalloc, relalloc, etc. for 16 bit compilers. Changed
  4.    argument of malloc, etc.,  to size_t (per ANSI draft). */
  5. /* 5/2/92 sb -- modified for Heat-n-Serve C to accomodate its 16-bit size_t */
  6. /* 5/5/92 sb -- split off realloc() & calloc() to reduce library drag */
  7.  
  8. #include <compiler.h>
  9. #include <stddef.h>    /* for size_t */
  10. #include <stdlib.h>
  11. #include <memory.h>
  12. #include <string.h>
  13. #include <assert.h>
  14. #include <unistd.h>
  15. #include "lib.h"
  16.  
  17. extern long _stksize;
  18. void *_malloc __PROTO((unsigned long));
  19.  
  20. /* minimum chunk to ask OS for */
  21. static size_t MINHUNK =    4096L;    /* default */
  22. static size_t MAXHUNK = 32*1024L; /* max. default */
  23.  
  24.     /* CAUTION: use _mallocChunkSize() to tailor to your environment,
  25.             do not make the default too large, as the compiler
  26.             gets screwed on a 1M machine otherwise (stack/heap clash)
  27.      */
  28.  
  29. /* linked list of free blocks struct defined in lib.h */
  30.  
  31. struct mem_chunk _mchunk_free_list = { VAL_FREE, NULL, 0L };
  32.  
  33. /* flag to control zero'ing of malloc'ed chunks */
  34. static int _ZeroMallocs = 0;
  35.  
  36. __EXTERN void _bzero __PROTO((void *, unsigned long));
  37.  
  38. #ifdef __GNUC__
  39. asm(".stabs \"_malloc\",5,0,0,__malloc"); /* dept of clean tricks */
  40. #endif
  41.  
  42. void * _malloc(n)
  43. unsigned long n; 
  44. {
  45.   struct mem_chunk *p, *q;
  46.   long sz;
  47.   extern void *_heapbase;
  48.   extern short _split_mem;
  49.  
  50. /* add a mem_chunk to required size and round up */
  51.   n = n + sizeof(struct mem_chunk);
  52.   n = (7 + n) & ~7;
  53. /* look for first block big enough in free list */
  54.   p = &_mchunk_free_list;
  55.   q = _mchunk_free_list.next;
  56.  
  57.   while ((q != NULL) && (q->size < n))
  58.     {
  59.     p = q;
  60.     q = q->next;
  61.     }
  62.  
  63. /* if not enough memory, get more from the system */
  64.   if (q == NULL) 
  65.     {
  66.     if (((!_split_mem) && (_heapbase != NULL)) || (n > MINHUNK))
  67.         sz = n;
  68.     else {
  69.         sz = MINHUNK;
  70.         if (MINHUNK < MAXHUNK)
  71.             MINHUNK *= 2;
  72.     }
  73.     if (_split_mem || _heapbase == NULL)
  74.       {
  75.         static int page_size = 0;
  76.         if (!page_size)
  77.           page_size = getpagesize ();
  78.         sz = (sz + page_size - 1) & -page_size;
  79.       }
  80.     q = (struct mem_chunk * )_sbrk(sz);
  81.  
  82.     if (((long)q) == -1)         /* can't alloc any more? */
  83.         return(NULL);
  84.  
  85.     /* Note: q may be below the highest allocated chunk */
  86.     p = &_mchunk_free_list;
  87.     while (p->next != NULL && q > p->next)
  88.       p = p->next;
  89.     q->size = sz;
  90.     q->next = p->next;
  91.     q->valid = VAL_FREE;
  92.     p->next = q;
  93.     }
  94.         
  95.   if (q->size > n + sizeof(struct mem_chunk))
  96.     {                /* split, leave part of free list */
  97.     q->size -= n;
  98.     q = (struct mem_chunk * )(((long) q) + q->size);
  99.     q->size = n;
  100.     q->valid = VAL_ALLOC;
  101.     }
  102.     else
  103.     {                /* just unlink it */
  104.     p->next = q->next;
  105.     q->valid = VAL_ALLOC;
  106.     }
  107.  
  108.   q->next = NULL;    
  109.   q++;    /* hand back ptr to after chunk desc */
  110.   if(_ZeroMallocs != 0)
  111.       _bzero((void *)q, (long)(n - sizeof(struct mem_chunk)));
  112.   
  113.   return((void * )q);
  114. }
  115.  
  116. void free(param)
  117.     void *param;
  118. {
  119.   struct mem_chunk *o, *p, *q, *s;
  120.   struct mem_chunk *r = (struct mem_chunk *) param;
  121.   extern void *_heapbase;
  122.   extern short _split_mem;
  123.  
  124. /* free(NULL) should do nothing */
  125.   if (r == 0)
  126.      return;
  127.  
  128. /* move back to uncover the mem_chunk */
  129.   r--;            /* there it is! */
  130.  
  131.   if (r->valid != VAL_ALLOC)
  132.     return;
  133.  
  134.   r->valid = VAL_FREE;
  135.  
  136. /* stick it into free list, preserving ascending address order */
  137.   o = NULL;
  138.   p = &_mchunk_free_list;
  139.   q = _mchunk_free_list.next;
  140.   while (q != NULL && q < r) 
  141.     {
  142.     o = p;
  143.     p = q;
  144.     q = q->next;
  145.     }
  146.  
  147. /* merge after if possible */
  148.   s = (struct mem_chunk * )(((long) r) + r->size);
  149.   if (q != NULL && s >= q) 
  150.     {
  151.     assert(s == q);
  152.     r->size += q->size;
  153.     q = q->next;
  154.     s->size = 0;
  155.     s->next = NULL;
  156.     }
  157.   r->next = q;
  158.     
  159. /* merge before if possible, otherwise link it in */
  160.   s = (struct mem_chunk * )(((long) p) + p->size);
  161.   if (s >= r && p != &_mchunk_free_list)
  162.     /* remember: r may be below &_mchunk_free_list in memory */
  163.     {
  164.     assert(s == r);
  165.     p->size += r->size;
  166.     p->next = r->next;
  167.     r->size = 0;
  168.     r->next = NULL;
  169.     s = (struct mem_chunk * )(((long) p) + p->size);
  170.     if ((!_split_mem) && _heapbase != NULL &&
  171.         s >= (struct mem_chunk *) _heapbase &&
  172.         s < (struct mem_chunk *) ((char *)_heapbase + _stksize)) {
  173.       assert(s == (struct mem_chunk *) _heapbase);
  174.       _heapbase = (void *) p;
  175.       _stksize += p->size;
  176.       o->next = p->next;    /* o is always != NULL here */
  177.     }
  178.     }
  179.     else
  180.         {
  181.       s = (struct mem_chunk * )(((long) r) + r->size);
  182.       if ((!_split_mem) && _heapbase != NULL &&
  183.           s >= (struct mem_chunk *) _heapbase &&
  184.           s < (struct mem_chunk *) ((char *)_heapbase + _stksize)) {
  185.         assert(s == (struct mem_chunk *) _heapbase);
  186.         _heapbase = (void *) r;
  187.         _stksize += r->size;
  188.         p->next = r->next;
  189.       } else p->next = r;
  190.     }
  191. }
  192.  
  193. /*
  194.  * Set zero block after malloc flag
  195.  */
  196. void _malloczero(yes)
  197. int yes;
  198. {
  199.     _ZeroMallocs = yes;
  200. }
  201.  
  202. /*
  203.  * tune chunk size
  204.  */
  205. void _mallocChunkSize (siz)
  206. size_t siz;
  207. {
  208.     MAXHUNK = MINHUNK = siz;
  209. }
  210.  
  211. #ifndef __GNUC__
  212. void * malloc(n)
  213. size_t n; 
  214. {
  215.   return _malloc((unsigned long) n);
  216. }
  217. #endif
  218.